package cn.wsalix.exception;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationListener;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerExceptionResolverComposite;

import cn.anlaser.exception.NutException;

import com.google.gson.Gson;

@Component("exceptionResolver")
public class ExceptionResolver extends HandlerExceptionResolverComposite
		implements AuthenticationListener {
	private static final Logger logger = LoggerFactory
			.getLogger(ExceptionResolver.class);

	/*
	 * @Autowired private LogService logService;
	 */
	@Transactional
	@Override
	public ModelAndView resolveException(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex) {
		ex.printStackTrace();
		ModelAndView modelAndView = null;
		HttpServletResponse httpServletResponse = (HttpServletResponse) response;
		httpServletResponse.setCharacterEncoding("UTF-8");
		HttpSession session = request.getSession(true);
		String backUrl = (String) session.getAttribute("backUrl");
		boolean isJson = false;
		// /Comment<Object> returnVO = new CommonVO<Object>();
		// returnVO.setCode(false);// nutEx.getCode());
		if (request.getRequestURL().toString().endsWith(".json")) {
			isJson = true;
		}
		// Log log = new Log();
		if (ex.getClass().getName()
				.equals("org.springframework.orm.jpa.JpaSystemException")) {
			// log.setCode(ex.getClass().getName());
			// log.setContent(ex.getMessage());
			if (ex.getCause().getCause() != null) {
				StringWriter sw = new StringWriter();
				PrintWriter pw = new PrintWriter(sw);
				ex.printStackTrace(pw);
				System.out.println(sw.toString().toUpperCase());
				// log.setRemark(sw.toString());
			}
		}

		if (ex instanceof AuthenticationException) {
			try {
				WebUtils.redirectToSavedRequest(request, response, "/site/login.do");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		logger.error("ERROR", ex + ":" + ex.getMessage());
		if (ex instanceof UnknownAccountException) {
			// returnVO.setMessage("无此帐号");
			//
		}
		if (ex instanceof UnauthorizedException) {
			UnauthorizedException unauthorizedException = (UnauthorizedException) ex;
			// returnVO.setMessage(unauthorizedException.getMessage());
		}
		// 可以自由处理各种异常逻辑
		if (ex instanceof org.springframework.web.HttpRequestMethodNotSupportedException) {

		}
		if (ex instanceof NutException) {
			if (request.getMethod().equals("POST")) {
				modelAndView = new ModelAndView("redirect:"
						+ request.getRequestURI());
				HttpSession requestOne = request.getSession(true);
				Map<String, Object> modelMap = (Map<String, Object>) requestOne
						.getAttribute("requestOne");
				modelAndView.addAllObjects(modelMap);
			} else {
				request.setAttribute("ex", ex);
				modelAndView = new ModelAndView("error");
			}
			NutException nutEx = (NutException) ex;
			// returnVO.setMessage(nutEx.getMessage());
			// log.setException(nutEx.exception());
		}
		// logService.add(log);
		if (isJson) {
			httpServletResponse.setCharacterEncoding("UTF-8");
			response.setHeader("Content-type", "text/html;charset=UTF-8");
			try {
				PrintWriter out = httpServletResponse.getWriter();
				// out.println(gson.toJson(returnVO));
				out.flush();
				out.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return null;
		}
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("ex", ex);
		return modelAndView;
	}

	private static Gson gson = new Gson();

	@Override
	public void onSuccess(AuthenticationToken token, AuthenticationInfo info) {
		logger.info("onSuccess");
	}

	@Override
	public void onFailure(AuthenticationToken token, AuthenticationException ae) {
		logger.error("onFailure");
	}

	@Override
	public void onLogout(PrincipalCollection principals) {
		logger.info("onLogout");
	}
	/*
	 * public LogService getLogService() { return logService; }
	 * 
	 * public void setLogService(LogService logService) { this.logService =
	 * logService; }
	 */
}
